<?php
/**
 * Created by PhpStorm.
 * User: Qch
 * Date: 2016/10/30
 * Time: 14:07
 */

namespace J\Schema;


use J\Schema\Collection\Collection;
use J\Exception;

class Artisan
{

    protected static $defaultStringLength = 125;

    protected static $line = '/*---------------------------------*/';

    /**
     * @param CollectionManager $cm
     * @param bool $install
     * @return string sql
     * @throws Exception
     */
    public static function start(CollectionManager $cm, $install = true)
    {
        $sql = [];

        $simple = $cm->isInner();
        $cm->iterateCollection(function (Collection $c) use (&$sql, $simple, $install) {
            $sql[] = self::createTableSql($c, $simple, $install);

            $sql[] = self::$line;

            // 内部表
            $inners = $c->inners();
            if ($inners) $sql[] = self::start($inners, $install);

        });

        return join("\n", $sql);
    }

    /**
     * 创建表
     * @param Collection $poem
     * @param bool $simple
     * @param bool $install
     * @return string
     * @throws Exception
     */
    protected static function createTableSql($poem, $simple = false, $install = true)
    {

        $table = $poem->getTableName();
        $str = "DROP TABLE IF EXISTS `$table`;";

        if (!$install) return $str . "\n";

        $sql = [];

        $sql[] = $str;
        $sql[] = "CREATE TABLE `$table` (";

        $sql[] = ($simple) ?
            '   id INT PRIMARY KEY NOT NULL,':
            '   id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,';

        $columns = [];
        $poem->elements()->iterateElements(function (IElement $e) use (&$columns) {
            $columns[] = '  ' . self::createColumnSql($e);
        });

        $sql[] = join(",\n", $columns);

        $sql[] = ($simple) ?
            ")ENGINE=InnoDB DEFAULT CHARSET=utf8;":
            ")ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;";

        return join("\n", $sql);
    }

    /**
     * 创建列
     * @param IElement $e
     * @return string
     */
    protected static function createColumnSql(IElement $e)
    {
        $sql = [];
        $sql[] = '`' . $e->getColumnName() . '`';
        $sql[] = self::makeFieldTypeString(
                $e->getColumnType(),
                $e->getAttribute()->get('length', -1)
            );
        if ($e->hasDefault()) {
            $sql[] = 'DEFAULT ' . $e->getAttribute()->get('default');
        }

        if (!$e->canNull()) {
            $sql[] = 'NOT NULL';
        }

        return join(' ', $sql);
    }

    /**
     * 创建列类型
     * @param $type
     * @param int $length
     * @return string
     */
    protected static function makeFieldTypeString($type, $length = -1)
    {
        static $column_type = [
            Syntax::VALUE_TINY       => 'TINYINT',
            Syntax::VALUE_SMALLINT   => 'SMALLINT',
            Syntax::VALUE_MEDIUMINT  => 'MEDIUMINT',
            Syntax::VALUE_INT        => 'INT',
            Syntax::VALUE_BIGINT     => 'BIGINT',
        ];

        if ($length === -1) $length = self::$defaultStringLength;

        switch($type & Syntax::MASK_MAIN_TYPE){
            case Syntax::VALUE_STRING :
                return ($type & Syntax::MASK_SUBTYPE) ? "VARCHAR($length)" : "CHAR($length)";
            case Syntax::VALUE_DATE_TIME :
                return 'INT';
            case Syntax::VALUE_FLOAT :
                return ($type & Syntax::MASK_SUBTYPE) ? "DOUBLE" : "FLOAT";
            case Syntax::VALUE_BOOL :
                return 'BIT(1)';
            case Syntax::VALUE_INTEGER :
                return array_isset($column_type, $type, 'INT');
            default:
                return 'VARCHAR('.self::$defaultStringLength.')';
        }
    }
}